/*
 * Copyright (c) 2024 iSOFT INFRASTRUCTURE SOFTWARE CO., LTD.
 * easyAda is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#ifndef ALLOCATE_H
#define ALLOCATE_H

#include <uapi/bootinfo.h>
#include <uapi/ipcbuffer.h>
#include <core/endpoint.h>

#define DISABLE_BUDDY_PAGE_TABLE

struct stack_ipcbuffer {
    char        stack[CONFIG_STACK_SIZE];
    ipcbuffer_t buf;
    bootinfo_t  bi;
    endpoint_t  faulthandler;
} ALIGNED(CONFIG_STACK_SIZE);

void          pagetable_test(void);
unsigned long allocator_pbase(unsigned long vbase);
unsigned long allocator_vbase(unsigned long pbase);

void  allocator_init(void);
void *allocator_alloc_block(unsigned int size);
int   allocator_free_block(unsigned long begin);

void show_pagetbale_alloctor_status(void);

int check_usram_region(void *begin, unsigned int size);

int allocator_free(unsigned long begin, unsigned int size);

void pagetable_alloctor_test(void);

void       *get_rs_stack(void);
bootinfo_t *get_rs_bootinfo(void);
void       *get_rs_ipcbuffer(void);
void       *get_rs_faulthandler(void);

static inline int vaddr_in_region(unsigned long va, const region_t *r)
{
    if ((va >= r->vbase) && (va <= (r->vbase + r->size))) {
        return 1;
    }
    return 0;
}

static inline int paddr_in_region(unsigned long pa, const region_t *r)
{
    if ((pa >= r->pbase) && (pa <= (r->pbase + r->size))) {
        return 1;
    }
    return 0;
}

static inline int get_bit0_pos(unsigned int number)
{
    int pos = 0;
    while (number != 0U) {
        if (!(number & 0x1U)) {
            break;
        }
        number >>= 1;
        pos++;
    }
    return pos;
}

static inline void set_pos_bit1(unsigned int *numebr, unsigned int pos)
{
    (*numebr) |= (unsigned int)((unsigned int)0x1 << pos);
}

static inline void set_pos_bit0(unsigned int *numebr, unsigned int pos)
{
    (*numebr) &= ~((unsigned int)1 << pos);
}

#endif
